/* 
 * File:   arrays.cpp
 * Author: Patrick W. M. Adams
 * Institution: Astrophysics, Cosmology and Gravity Centre,
 *              Department of Mathematics and Applied Mathematics,
 *              University of Cape Town
 *
 * Created on 13 March 2012, 4:05 AM
 */

#include "arrays.h"

//constructor
Arrays::Arrays(){
    
    //blank
    
}//end constructor

//constructor
Arrays::Arrays(unsigned int x, unsigned int y, unsigned int z){
    
    xDimSize = x;
    yDimSize = y;
    zDimSize = z;
    Lx = 0, Ly = 0, Lz = 0; //x-, y- and z-lengths
    h = 0, dt = 0, tmax = 0; //spatial step size, temporal step size, max time
    
    //inflate array dimensions; check for bad_alloc
    
    try{
    
        A = new double***[xDimSize];
    
        for(int i = 0; i < xDimSize; i++){
        
                A[i] = new double**[yDimSize];
        
                for(int j = 0; j < yDimSize; j++){
            
                        A[i][j] = new double*[zDimSize];
            
                        for(int k = 0; k < zDimSize; k++){
                
                                A[i][j][k] = new double[3];
                
                                for(int l = 0; l < 3; l++){
                    
                                        A[i][j][k][l] = 0.0; 
                                        //initialize to a set value for safety
                    
                                }
                
                        }
            
                }
        
        }
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }    
    
    /*array.resize(xDimSize);
    
    for(int i = 0; i < xDimSize; i++){
        
        array[i].resize(yDimSize);
        
        for(int j = 0; j < yDimSize; j++){
            
            array[i][j].resize(zDimSize);
            
            for(int k = 0; k < zDimSize; k++){
                
                array[i][j][k].resize(mFArray);
                
            }
            
        }
        
    }*/
    
}//end constructor

//constructor
Arrays::Arrays(unsigned int x, unsigned int y, unsigned int z, unsigned int w){
    
    xDimSize = x;
    yDimSize = y;
    zDimSize = z;
    wDimSize = w;
    Lx = 0, Ly = 0, Lz = 0; //x-, y- and z-lengths
    h = 0, dt = 0, tmax = 0; //spatial step size, temporal step size, max time
    
    //inflate array dimensions; check for bad_alloc
    
    try{
    
        A = new double***[xDimSize];
    
        for(int i = 0; i < xDimSize; i++){
        
                A[i] = new double**[yDimSize];
        
                for(int j = 0; j < yDimSize; j++){
            
                        A[i][j] = new double*[zDimSize];
            
                        for(int k = 0; k < zDimSize; k++){
                
                                A[i][j][k] = new double[wDimSize];
                
                                for(int l = 0; l < wDimSize; l++){
                    
                                        A[i][j][k][l] = 0.0; 
                                        //initialize to a set value for safety
                    
                                }
                
                        }
            
                }
        
        }
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }    
    
    /*array.resize(xDimSize);
    
    for(int i = 0; i < xDimSize; i++){
        
        array[i].resize(yDimSize);
        
        for(int j = 0; j < yDimSize; j++){
            
            array[i][j].resize(zDimSize);
            
            for(int k = 0; k < zDimSize; k++){
                
                array[i][j][k].resize(mFArray);
                
            }
            
        }
        
    }*/
    
}//end constructor

//copy constructor
Arrays::Arrays(const Arrays&){
    
    //empty for now
    
}//end copy constructor

//destructor
Arrays::~Arrays(){
    
    //std::cout << "Paying a visit to Arrays destructor..." << std::endl;
    
    for(int i = 0; i < xDimSize; i++){
        
        for(int j = 0; j < yDimSize; j++){
            
            for(int k = 0; k < zDimSize; k++){
                
                delete[] A[i][j][k];
                
            }
            
            delete[] A[i][j];
            
        }
        
        delete[] A[i];
        
    }
    
    delete[] A;
    
    //std::cout << "f is dead!" << std::endl;
    
}//end destructor

//getArraysDim
unsigned int Arrays::getArraysDim(unsigned int dimNo){
    
    //check which dimension size to return
    if(dimNo == 0){
       
        return xDimSize;
        
    } else if(dimNo == 1){
        
        return yDimSize;
        
    } else if(dimNo == 2){
        
        return zDimSize;
        
    } else{
        
        return 0;
        
    }
    
}//end getArraysDim

//operator=
Arrays& Arrays::operator=(const Arrays& a){
    
    //check for (invalid) self-assignment
    if(this != &a){
        
        //fill in...
        
    }
    
    return *this;
    
}//end operator=

void Arrays::inflateA(){
    
    //inflate array dimensions; check for bad_alloc
    
    try{
    
        A = new double***[3];
    
        for(int i = 0; i < 3; i++){
        
                A[i] = new double**[xDimSize];
        
                for(int j = 0; j < xDimSize; j++){
            
                        A[i][j] = new double*[yDimSize];
            
                        for(int k = 0; k < yDimSize; k++){
                
                                A[i][j][k] = new double[zDimSize];
                
                                for(int l = 0; l < zDimSize; l++){
                    
                                        A[i][j][k][l] = 0.0; 
                                        //initialize to a set value for safety
                    
                                }
                
                        }
            
                }
        
        }
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
}

void Arrays::inflateVel(){
    
    //inflate array dimensions; check for bad_alloc
    
    try{
    
        vel = new double***[3];
    
        for(int i = 0; i < 3; i++){
        
                vel[i] = new double**[xDimSize];
        
                for(int j = 0; j < xDimSize; j++){
            
                        vel[i][j] = new double*[yDimSize];
            
                        for(int k = 0; k < yDimSize; k++){
                
                                vel[i][j][k] = new double[zDimSize];
                
                                for(int l = 0; l < zDimSize; l++){
                    
                                        vel[i][j][k][l] = 0.0; 
                                        //initialize to a set value for safety
                    
                                }
                
                        }
            
                }
        
        }
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
}

void Arrays::inflateXarr(int xA, int xB){
    
    //inflate array dimensions; check for bad_alloc   
    try{
    
        xaxis = new double[Lx];
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
    xaxis[0] = xA, xaxis[Lx-1] = xB; //set axis bounds
    
    //fill in everything else
    for(int i = 1; i < Lx - 1; i++){
        
        xaxis[i] = xA + i*h;
        
    }
    
}

void Arrays::inflateYarr(int yA, int yB){
    
    //inflate array dimensions; check for bad_alloc   
    try{
    
        yaxis = new double[Ly];
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
    yaxis[0] = yA, yaxis[Ly-1] = yB; //set axis bounds
    
    //fill in everything else
    for(int i = 1; i < Ly - 1; i++){
        
        yaxis[i] = yA + i*h;
        
    }
    
}

void Arrays::inflateZarr(int zA, int zB){
    
    //inflate array dimensions; check for bad_alloc   
    try{
    
        zaxis = new double[Lz];
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
    zaxis[0] = zA, zaxis[Lz-1] = zB; //set axis bounds
    
    //fill in everything else
    for(int i = 1; i < Lz - 1; i++){
        
        zaxis[i] = zA + i*h;
        
    }
    
}

void Arrays::inflateTarr(int tA){
    
    //inflate array dimensions; check for bad_alloc   
    try{
    
        taxis = new double[nsteps];
        
    } catch(std::bad_alloc& e){
        
        std::cerr << "BAD_ALLOC ERROR: " << e.what() <<
                ". Try smaller grid dimensions." << std::endl;
        
    }
    
    taxis[0] = tA, xaxis[nsteps-1] = tmax; //set axis bounds
    
    //fill in everything else
    for(int i = 1; i < nsteps - 1; i++){
        
        taxis[i] = tA + i*dt;
        
    }
    
}